﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using System.Threading;
using System.Data.SqlClient;
using System.Data.Common;
using Apq_DBTools.Forms;
using Apq.TreeListView;
using System.IO;
using org.mozilla.intl.chardet;
using Apq.DllImports;
using System.Collections;
using MySql.Data.MySqlClient;
using System.Text.RegularExpressions;

namespace Apq_DBTools.Forms
{
	public partial class DBStructCompare : Apq.Windows.Forms.DockDocForm
	{
		private static string _DataCfgFolder = string.Empty;
		/// <summary>
		/// 方案文件夹
		/// </summary>
		private string DataCfgFolder
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_DataCfgFolder))
				{
					_DataCfgFolder = System.IO.Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\DataCfg";
					if (!Directory.Exists(_DataCfgFolder))
					{
						Directory.CreateDirectory(_DataCfgFolder);
					}
				}
				return _DataCfgFolder;
			}
		}

		private Apq.Windows.Forms.DockForms.ErrList ErrList = new Apq.Windows.Forms.DockForms.ErrList();

		public DBStructCompare()
		{
			InitializeComponent();

			//Apq.Windows.Forms.DataGridViewHelper.SetDefaultStyle(dataGridView1);
			Apq.Windows.Forms.DataGridViewHelper.AddBehaivor(dataGridView1);
			Apq.Windows.Forms.DataGridViewHelper.SetDefaultStyle(dgvTableKey);
			Apq.Windows.Forms.DataGridViewHelper.AddBehaivor(dgvTableKey);
		}

		private Apq.Data.Common.DBProduct _DBConnectionType = Apq.Data.Common.DBProduct.MySql;
		private DbConnection _DBConnection;

		public override void SetUILang(Apq.UILang.UILang UILang)
		{
			Text = Apq.GlobalObject.UILang["脚本生成"];
			TabText = Text;

			tsbConnectDB.Text = Apq.GlobalObject.UILang["连接"];
			tsmiRefresh.Text = Apq.GlobalObject.UILang["刷新(&F)"];

			toolStripLabel1.Text = Apq.GlobalObject.UILang["方案"];
			tsbSaveDataCfg.Text = Apq.GlobalObject.UILang["保存(&S)"];

			tssbSelect.Text = Apq.GlobalObject.UILang["选择"];
			tsmiSelectAll.Text = Apq.GlobalObject.UILang["全选(&A)"];
			tsmiSelectReverse.Text = Apq.GlobalObject.UILang["反选(&R)"];
			tsmiSelectTable.Text = Apq.GlobalObject.UILang["表(&T)"];
			tsmiSelectProc.Text = Apq.GlobalObject.UILang["存储过程(&P)"];
			tsmiSelectTrigger.Text = Apq.GlobalObject.UILang["触发器(&I)"];

			tssbDataGen.Text = Apq.GlobalObject.UILang["数据生成选项"];
			tsmiDataExists.Text = Apq.GlobalObject.UILang["不存在时添加"];
			tsmiDataDelete.Text = Apq.GlobalObject.UILang["先删除后添加"];
			tsmiDataInsert.Text = Apq.GlobalObject.UILang["直接添加"];

			tssbGenSql.Text = Apq.GlobalObject.UILang["生成"];
			tsmiMeta.Text = Apq.GlobalObject.UILang["元数据脚本(&M)"];
			tsmiData.Text = Apq.GlobalObject.UILang["初始化数据(&D)"];

			// 列
			dgvcCheckState.HeaderText = Apq.GlobalObject.UILang["选择"];
			dgvcObjectType.HeaderText = Apq.GlobalObject.UILang["类型"];
			dgvcSchemaName.HeaderText = Apq.GlobalObject.UILang["架构"];
			dgvcObjectName.HeaderText = Apq.GlobalObject.UILang["名称"];
			//dgvcPrimaryKeys.HeaderText = Apq.GlobalObject.UILang["数据Key"];
			//dgvcDataFilter.HeaderText = Apq.GlobalObject.UILang["数据过滤"];

			dgvcSchemaName1.HeaderText = Apq.GlobalObject.UILang["架构"];
			dgvcTableName1.HeaderText = Apq.GlobalObject.UILang["表名"];
			dgvcPrimaryKeys1.HeaderText = Apq.GlobalObject.UILang["数据Key"];
			dgvcDataFilter1.HeaderText = Apq.GlobalObject.UILang["数据过滤"];

			sfdMeta.Filter = Apq.GlobalObject.UILang["SQL 文件(*.sql)|*.sql|所有文件(*.*)|*.*"];
		}

		private void SqlGen_Load(object sender, EventArgs e)
		{
			_xsd.Meta.RowChanged += new DataRowChangeEventHandler(Meta_RowChanged);

			tscbSqlProduct.SelectedIndex = 0;

			//tsbConnectDB_ButtonClick(sender, e);
		}

		void Meta_RowChanged(object sender, DataRowChangeEventArgs e)
		{
			if (e.Action == DataRowAction.Change)
			{
				e.Row.AcceptChanges();
				Menu_SetCheckState();
			}
		}

		#region IDataShow 成员
		/// <summary>
		/// 前期准备(如数据库连接或文件等)
		/// </summary>
		public override void InitDataBefore()
		{
			#region 数据库连接
			#endregion
		}
		/// <summary>
		/// 初始数据(如Lookup数据等)
		/// </summary>
		/// <param name="ds"></param>
		public override void InitData(DataSet ds)
		{
			#region 准备数据集结构
			#endregion

			#region 加载所有查找表
			_xsd.dic_ObjectType.InitData();

			// 读取方案文件列表
			if (System.IO.Directory.Exists(DataCfgFolder))
			{
				string strDataCfgName = GlobalObject.XmlConfigChain[this.GetType(), "DataCfgName"];
				string[] aryFiles = System.IO.Directory.GetFiles(DataCfgFolder, "*.xml");
				for (int i = 0; i < aryFiles.Length; i++)
				{
					string strFileName = System.IO.Path.GetFileNameWithoutExtension(aryFiles[i]);
					tscbDataCfg.Items.Add(strFileName);

					if (strFileName.Equals(strDataCfgName, StringComparison.OrdinalIgnoreCase))
					{
						tscbDataCfg.SelectedIndex = i;
					}
				}
			}
			#endregion
		}
		/// <summary>
		/// 加载数据
		/// </summary>
		/// <param name="ds"></param>
		public override void LoadData(DataSet ds)
		{
		}
		#endregion

		public void UIEnable(bool Enable)
		{
			dataGridView1.Enabled = Enable;
			tsbConnectDB.Enabled = Enable;
			tssbGenSql.Enabled = Enable;

			Cursor = Enable ? Cursors.Default : Cursors.WaitCursor;
		}

		private void SqlGen_FormClosing(object sender, FormClosingEventArgs e)
		{
		}

		private void SqlGen_Activated(object sender, EventArgs e)
		{
		}

		private void SqlGen_Deactivate(object sender, EventArgs e)
		{

		}

		private void Menu_SetCheckState()
		{
			bool hasSameCheckState_Table = true;// 记录所有行是否为同一种选中状态
			int iCheckState_Table = -1;// 记录上一行选中状态

			bool hasSameCheckState_Proc = true;// 记录所有行是否为同一种选中状态
			int iCheckState_Proc = -1;// 记录上一行选中状态

			bool hasSameCheckState_Trigger = true;// 记录所有行是否为同一种选中状态
			int iCheckState_Trigger = -1;// 记录上一行选中状态

			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				if (dr.ObjectType == 1)
				{
					if (iCheckState_Table >= 0 && iCheckState_Table != Apq.Convert.ChangeType<int>(dr._CheckState))
					{
						hasSameCheckState_Table = false;
					}
					iCheckState_Table = Apq.Convert.ChangeType<int>(dr._CheckState);
				}
				if (dr.ObjectType == 2)
				{
					if (iCheckState_Proc >= 0 && iCheckState_Proc != Apq.Convert.ChangeType<int>(dr._CheckState))
					{
						hasSameCheckState_Proc = false;
					}
					iCheckState_Proc = Apq.Convert.ChangeType<int>(dr._CheckState);
				}
				if (dr.ObjectType == 3)
				{
					if (iCheckState_Trigger >= 0 && iCheckState_Trigger != Apq.Convert.ChangeType<int>(dr._CheckState))
					{
						hasSameCheckState_Trigger = false;
					}
					iCheckState_Trigger = Apq.Convert.ChangeType<int>(dr._CheckState);
				}
			}

			if (hasSameCheckState_Table && iCheckState_Table >= 0)
			{
				tsmiSelectTable.CheckState = Apq.Convert.ChangeType<CheckState>(iCheckState_Table);
			}
			if (hasSameCheckState_Proc && iCheckState_Proc >= 0)
			{
				tsmiSelectProc.CheckState = Apq.Convert.ChangeType<CheckState>(iCheckState_Proc);
			}
			if (hasSameCheckState_Trigger && iCheckState_Trigger >= 0)
			{
				tsmiSelectTrigger.CheckState = Apq.Convert.ChangeType<CheckState>(iCheckState_Trigger);
			}
		}

		// 刷新
		private void tsbRefresh_Click(object sender, EventArgs e)
		{
			try
			{
				_DBConnection.Open();
			}
			catch
			{
				MessageBox.Show(this, Apq.GlobalObject.UILang["数据库未连接或已断开"]);
				return;
			}
			finally
			{
				Apq.Data.Common.DbConnectionHelper.Close(_DBConnection);
			}

			ErrList.ErrXSD.ErrList.Clear();
			_xsd.Meta.Rows.Clear();
			_xsd.dbv_trigger.Rows.Clear();
			_xsd.dbv_proc.Rows.Clear();
			_xsd.dbv_column.Rows.Clear();
			_xsd.dbv_table.Rows.Clear();

			try
			{
				Apq.Data.Common.DbConnectionHelper dch = new Apq.Data.Common.DbConnectionHelper(_DBConnection);
				DbDataAdapter dda = dch.CreateAdapter();
				if (_DBConnectionType == Apq.Data.Common.DBProduct.MySql)
				{
					// 表
					dda.SelectCommand.CommandText = @"
SELECT `TABLE_SCHEMA` as SchemaName,`Table_Name` as TableName,`ENGINE`,`CREATE_OPTIONS`,`TABLE_COMMENT`,'' as PrimaryKeys
  FROM `information_schema`.`TABLES`
 WHERE `TABLE_SCHEMA` = DATABASE() AND `Table_Name` NOT IN ('dbv_BuildLog','dbv_table','dbv_column','dbv_trigger','dbv_view','dbv_proc');
";
					dda.Fill(_xsd.dbv_table);
					// 列
					dda.SelectCommand.CommandText = @"
SELECT `COLUMN_NAME` as ColName,
	CONVERT(`COLUMN_DEFAULT` USING utf8) AS DefaultValue,
	CASE `IS_NULLABLE` WHEN 'NO' THEN 0 ELSE 1 END as NullAble,
	`DATA_TYPE`,`CHARACTER_MAXIMUM_LENGTH`,`CHARACTER_OCTET_LENGTH`,`NUMERIC_PRECISION`,`NUMERIC_SCALE`,`CHARACTER_SET_NAME`,`COLLATION_NAME`,
	CONVERT(`COLUMN_TYPE` USING utf8) AS COLUMN_TYPE,
	`COLUMN_KEY`,
	CASE WHEN INSTR(`EXTRA`,'auto_increment') > 0 THEN 1 ELSE 0 END as is_auto_increment,
	`COLUMN_COMMENT`,c.`TABLE_SCHEMA` as SchemaName,c.`TABLE_NAME` as TableName
  FROM `information_schema`.`COLUMNS` c 
	INNER JOIN `information_schema`.`TABLES` t ON c.`TABLE_SCHEMA` = t.`TABLE_SCHEMA` AND c.`TABLE_NAME` = t.`TABLE_NAME` 
	-- INNER JOIN `dbv_table` dt ON t.`TABLE_SCHEMA` = dt.`SchemaName` AND t.`TABLE_NAME` = dt.`TableName`
 WHERE c.`TABLE_SCHEMA` = DATABASE() AND t.`Table_Name` NOT IN ('dbv_BuildLog','dbv_table','dbv_column','dbv_trigger','dbv_view','dbv_proc');
";
					dda.Fill(_xsd.dbv_column);
					// 视图
					dda.SelectCommand.CommandText = @"
SELECT `TABLE_SCHEMA` as SchemaName,`Table_Name` as TableName,`VIEW_DEFINITION`
  FROM `information_schema`.`VIEWS`
 WHERE `TABLE_SCHEMA` = DATABASE();
";
					dda.Fill(_xsd.dbv_view);
					// 存储过程,函数
					dda.SelectCommand.CommandText = @"
SELECT `db` AS SchemaName,`name` AS ProcName,
	CASE `type` WHEN 'FUNCTION' THEN 4 ELSE 2 END AS type,
	CONVERT(`param_list` USING utf8) AS param_list,
	CONVERT(`returns` USING utf8) AS RETURNS,
	CONVERT(`body` USING utf8) AS body,
	`comment`
  FROM `mysql`.`proc`
 WHERE `db` = DATABASE() AND `name` NOT IN ('Apq_CreateNewTable');
";
					dda.Fill(_xsd.dbv_proc);
					// 触发器
					dda.SelectCommand.CommandText = @"
SELECT `TRIGGER_SCHEMA` as SchemaName,`TRIGGER_NAME` as TriName,`EVENT_MANIPULATION`,`EVENT_OBJECT_TABLE` as TableName,`ACTION_ORDER`,`ACTION_CONDITION`,`ACTION_STATEMENT`,`ACTION_ORIENTATION`,`ACTION_TIMING`
  FROM `information_schema`.`TRIGGERS` t
 WHERE t.`TRIGGER_SCHEMA` = DATABASE();
";
					dda.Fill(_xsd.dbv_trigger);

					// 为列设置TID
					foreach (SqlGen_XSD.dbv_columnRow dr in _xsd.dbv_column.Rows)
					{
						SqlGen_XSD.dbv_tableRow drT = _xsd.dbv_table.FindByTableName(dr.SchemaName, dr.TableName);
						dr.TID = drT.TID;
					}
					// 为表查找主键列
					foreach (SqlGen_XSD.dbv_tableRow dr in _xsd.dbv_table.Rows)
					{
						SqlGen_XSD.dbv_columnRow[] drCs = dr.GetChildRows("FK_dbv_table_dbv_column") as SqlGen_XSD.dbv_columnRow[];
						string strCols = string.Empty;
						foreach (SqlGen_XSD.dbv_columnRow drc in drCs)
						{
							if ("PRI".Equals(drc.COLUMN_KEY, StringComparison.OrdinalIgnoreCase))
							{
								strCols += ",`" + drc.ColName + "`";
							}
						}
						if (strCols.Length > 0)
						{
							dr.PrimaryKeys = strCols.Substring(1);
						}
					}
					// 将名称加到元数据表，用于界面显示
					int nCheckState = Apq.Convert.ChangeType<int>(tsmiSelectTable.CheckState);
					foreach (SqlGen_XSD.dbv_tableRow drT in _xsd.dbv_table.Rows)
					{//表
						SqlGen_XSD.MetaRow drMeta = _xsd.Meta.NewMetaRow();
						drMeta.ObjectType = 1;
						drMeta._CheckState = nCheckState;
						drMeta.SchemaName = drT.SchemaName;
						drMeta.ObjectName = drT.TableName;
						drMeta.PrimaryKeys = drT.PrimaryKeys;
						_xsd.Meta.Rows.Add(drMeta);
					}
					foreach (SqlGen_XSD.dbv_viewRow drV in _xsd.dbv_view.Rows)
					{//视图
						SqlGen_XSD.MetaRow drMeta = _xsd.Meta.NewMetaRow();
						drMeta.ObjectType = 6;
						drMeta._CheckState = nCheckState;
						drMeta.SchemaName = drV.SchemaName;
						drMeta.ObjectName = drV.TableName;
						_xsd.Meta.Rows.Add(drMeta);
					}
					nCheckState = Apq.Convert.ChangeType<int>(tsmiSelectTrigger.CheckState);
					foreach (SqlGen_XSD.dbv_triggerRow drTri in _xsd.dbv_trigger.Rows)
					{//触发器
						SqlGen_XSD.MetaRow drMeta = _xsd.Meta.NewMetaRow();
						drMeta.ObjectType = 3;
						drMeta._CheckState = nCheckState;
						drMeta.SchemaName = drTri.SchemaName;
						drMeta.ObjectName = drTri.TriName;
						_xsd.Meta.Rows.Add(drMeta);
					}
					nCheckState = Apq.Convert.ChangeType<int>(tsmiSelectProc.CheckState);
					foreach (SqlGen_XSD.dbv_procRow drP in _xsd.dbv_proc.Rows)
					{//存储过程,函数
						SqlGen_XSD.MetaRow drMeta = _xsd.Meta.NewMetaRow();
						drMeta.ObjectType = drP.type;
						drMeta._CheckState = nCheckState;
						drMeta.SchemaName = drP.SchemaName;
						drMeta.ObjectName = drP.ProcName;
						_xsd.Meta.Rows.Add(drMeta);
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
			finally
			{
				if (ErrList.ErrXSD.ErrList.Rows.Count > 0)
				{
					ErrList.Show(DockFrame.DockDoc);
				}
			}
		}

		private void tsbConnectDB_ButtonClick(object sender, EventArgs e)
		{
			// 连接到数据库并执行刷新动作
			Apq.Windows.Forms.DBConnector DBConnector = new Apq.Windows.Forms.DBConnector();
			if (DBConnector.ShowDialog(GlobalObject.MainForm) == System.Windows.Forms.DialogResult.OK)
			{
				Text = Apq.GlobalObject.UILang["脚本生成"] + " - " + DBConnector.DBConnection.DataSource
					 + " - " + DBConnector.DBConnection.Database;

				_DBConnectionType = DBConnector.DBSelected;
				_DBConnection = DBConnector.DBConnection;
				tsbRefresh_Click(sender, e);

				this.Show();
			}
		}
		// 生成元数据语句并保存到文件
		private void tsmiMeta_Click(object sender, EventArgs e)
		{
			if (tscbSqlProduct.SelectedIndex != 0)
			{
				string strExMsg = Apq.GlobalObject.UILang["尚未实现！"];
				//ErrList.AddRow(DateTime.Now, 4, 16, Apq.GlobalObject.UILang["尚未实现"], strExMsg);
				MessageBox.Show(this, strExMsg);
				return;
			}
			try
			{
				_DBConnection.Open();
			}
			catch
			{
				MessageBox.Show(this, Apq.GlobalObject.UILang["数据库未连接或已断开"]);
				return;
			}
			finally
			{
				Apq.Data.Common.DbConnectionHelper.Close(_DBConnection);
			}

			StringBuilder sb = new StringBuilder();
			sfdMeta.InitialDirectory = GlobalObject.XmlConfigChain[this.GetType(), "sfdMeta_InitialDirectory"];
			if (sfdMeta.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
			{
				GlobalObject.XmlConfigChain[this.GetType(), "sfdMeta_InitialDirectory"] = Path.GetDirectoryName(sfdMeta.FileName);

				if (tscbSqlProduct.SelectedIndex == 0)
				{
					#region 创建元数据表
					// 为列表中已选中的项生成语句，语句完成将这些项插入到dbv_table,dbv_column,dbv_proc中
					sb.Append(string.Format(@"/* -------------------------------------------------------------------------------------------------
{1}
该文件由Apq_DBTools自动生成
不含索引,外键

数据库创建
dbv表创建
元数据导入
基本存储过程（根据元数据无损构建数据库）
视图
触发器
存储过程
函数
====================================================================================================
*/
CREATE DATABASE IF NOT EXISTS `{0}` DEFAULT CHARACTER SET utf8;
USE `{0}`;
SET FOREIGN_KEY_CHECKS=0;", _DBConnection.Database, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
					sb.Append(@"
-- 元数据表 -----------------------------------------------------------------------------------------");
					string strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_BuildLog.sql";
					string strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_table.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_column.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_view.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_trigger.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\dbv_proc.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					sb.Append(@"
-- =================================================================================================

-- 基本存储过程 -------------------------------------------------------------------------------------");
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\Apq_BuildStruct.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\Apq_CreateNewTable.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					strFilePath = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\Sql\MySql\Apq_BuildTable.sql";
					strFileContent = Environment.NewLine + File.ReadAllText(strFilePath) + Environment.NewLine;
					sb.Append(strFileContent);
					sb.Append(@"
-- =================================================================================================

-- 元数据 ------------------------------------------------------------------------------------------"
					);
					#endregion

					#region 填充元数据
					foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
					{
						#region 表
						if (dr.ObjectType == 1
							//&& dr._CheckState == 1
						)
						{
							SqlGen_XSD.dbv_tableRow drT = _xsd.dbv_table.FindByTableName(dr.SchemaName, dr.ObjectName);
							sb.Append(string.Format(@"

-- 表:{0}
INSERT INTO `dbv_table`(`TID`,`SchemaName`,`TableName`,`ENGINE`,`CREATE_OPTIONS`,`TABLE_COMMENT`,`PrimaryKeys`) VALUES({1},{2},{3},{4},{5},{6},{7});",
									drT.TableName,
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT.TID),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT.SchemaName),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT.TableName),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT["ENGINE"]),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT["CREATE_OPTIONS"]),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT["TABLE_COMMENT"]),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drT.PrimaryKeys)
								)
							);
							SqlGen_XSD.dbv_columnRow[] drCs = drT.GetChildRows("FK_dbv_table_dbv_column") as SqlGen_XSD.dbv_columnRow[];
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								sb.Append(string.Format(@"
INSERT INTO `dbv_column`(`TID`,`ColName`,`DefaultValue`,`NullAble`,`DATA_TYPE`,`CHARACTER_MAXIMUM_LENGTH`,`CHARACTER_OCTET_LENGTH`,`NUMERIC_PRECISION`,`NUMERIC_SCALE`,`CHARACTER_SET_NAME`,`COLLATION_NAME`,`COLUMN_TYPE`,`COLUMN_KEY`,`is_auto_increment`,`COLUMN_COMMENT`,`SchemaName`,`TableName`) VALUES({0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16});",
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.TID),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.ColName),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["DefaultValue"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.NullAble),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.DATA_TYPE),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["CHARACTER_MAXIMUM_LENGTH"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["CHARACTER_OCTET_LENGTH"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["NUMERIC_PRECISION"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["NUMERIC_SCALE"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["CHARACTER_SET_NAME"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["COLLATION_NAME"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.COLUMN_TYPE),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["COLUMN_KEY"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.is_auto_increment),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC["COLUMN_COMMENT"]),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.SchemaName),
										Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.TableName)
									)
								);
							}
						}
						#endregion
					}
					sb.Append(@"

CALL Apq_BuildStruct();");
					foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
					{
						#region 视图
						if (dr.ObjectType == 6
							//&& dr._CheckState == 1
						)
						{
							SqlGen_XSD.dbv_viewRow drV = _xsd.dbv_view.FindByTableName(dr.SchemaName, dr.ObjectName);
							sb.Append(string.Format(@"

-- 视图:{0}
DROP VIEW IF EXISTS `{0}`;
DROP TABLE IF EXISTS `{0}`;
DELIMITER $$
CREATE VIEW `{0}` AS {1}$$
DELIMITER ;",
									drV.TableName,
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drV.VIEW_DEFINITION)
								)
							);
						}
						#endregion
					}
					foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
					{
						#region 触发器
						if (dr.ObjectType == 3
							//&& dr._CheckState == 1
						)
						{
							SqlGen_XSD.dbv_triggerRow drTri = _xsd.dbv_trigger.FindByTriName(dr.SchemaName, dr.ObjectName);
							sb.Append(string.Format(@"

-- 触发器:{0}
DROP TRIGGER IF EXISTS `{0}`;
DELIMITER $$
CREATE TRIGGER `{0}` {7} {1} ON `{2}` FOR EACH ROW
{5}$$
DELIMITER ;",
									drTri.TriName,
									drTri.EVENT_MANIPULATION,
									drTri.TableName,
									drTri.ACTION_ORDER,
									drTri["ACTION_CONDITION"],
									drTri.ACTION_STATEMENT,
									drTri.ACTION_ORIENTATION,
									drTri.ACTION_TIMING
								)
							);
						}
						#endregion
						#region 存储过程
						if (dr.ObjectType == 2
							//&& dr._CheckState == 1
						)
						{
							SqlGen_XSD.dbv_procRow drP = _xsd.dbv_proc.FindByProcName(dr.SchemaName, dr.ObjectName);
							sb.Append(string.Format(@"

-- 存储过程:{0}
DROP PROCEDURE IF EXISTS `{0}`;
DROP FUNCTION IF EXISTS `{0}`;
DELIMITER $$
CREATE PROCEDURE `{0}`({1})
COMMENT {3}
{2}$$
DELIMITER ;",
									drP.ProcName,
									drP.param_list,
									drP.body,
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drP.comment)
								)
							);
						}
						#endregion
						#region 函数
						if (dr.ObjectType == 4
							//&& dr._CheckState == 1
						)
						{
							SqlGen_XSD.dbv_procRow drP = _xsd.dbv_proc.FindByProcName(dr.SchemaName, dr.ObjectName);
							sb.Append(string.Format(@"

-- 函数:{0}
DROP PROCEDURE IF EXISTS `{0}`;
DROP FUNCTION IF EXISTS `{0}`;
DELIMITER $$
CREATE FUNCTION `{0}`({1})
RETURNS {2}
COMMENT {4}
{3}$$
DELIMITER ;",
									drP.ProcName,
									drP.param_list,
									drP.returns,
									drP.body,
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drP.comment)
								)
							);
						}
						#endregion
					}
					#endregion

					sb.Append(@"
-- =================================================================================================

COMMIT;
");
				}
				if (tscbSqlProduct.SelectedIndex == 1)
				{
					MessageBox.Show(this, Apq.GlobalObject.UILang["尚未实现！"]);
					return;
				}

				File.WriteAllText(sfdMeta.FileName, sb.ToString());
				MessageBox.Show(this, Apq.GlobalObject.UILang["保存成功！"]);

				if (ErrList.ErrXSD.ErrList.Rows.Count > 0)
				{
					ErrList.Show(DockFrame.DockDoc);
				}
			}
		}
		// 生成初始数据语句并保存到文件
		private void tsmiData_Click(object sender, EventArgs e)
		{
			try
			{
				_DBConnection.Open();
			}
			catch
			{
				MessageBox.Show(this, Apq.GlobalObject.UILang["数据库未连接或已断开"]);
				return;
			}
			finally
			{
				Apq.Data.Common.DbConnectionHelper.Close(_DBConnection);
			}

			Apq.Data.Common.DbConnectionHelper dch = new Apq.Data.Common.DbConnectionHelper(_DBConnection);
			StringBuilder sb = new StringBuilder();
			sfdMeta.InitialDirectory = GlobalObject.XmlConfigChain[this.GetType(), "sfdMeta_InitialDirectory"];
			if (sfdMeta.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
			{
				GlobalObject.XmlConfigChain[this.GetType(), "sfdMeta_InitialDirectory"] = Path.GetDirectoryName(sfdMeta.FileName);

				if (tscbSqlProduct.SelectedIndex == 0)
				{
					#region MySql
					#region 初始数据文件头
					// 为列表中已选中的表生成初始化语句，语句功能：完成将数据库中的数据插入到对应的表中，按主键添加
					sb.Append(string.Format(@"/* -------------------------------------------------------------------------------------------------
{1}
该文件由Apq_DBTools自动生成
生成后请删除多余数据

初始数据
====================================================================================================
*/
USE `{0}`;
SET FOREIGN_KEY_CHECKS=0;", _DBConnection.Database, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
					if (tsmiDataExists.Checked)
					{
						sb.Append(string.Format(@"

-- 为INSERT准备临时表
DROP TABLE IF EXISTS `_Apq_Ins`;
CREATE TEMPORARY TABLE `_Apq_Ins` (
  `_ID` INT(11) DEFAULT NULL
) ENGINE = HEAP;
INSERT INTO `_Apq_Ins`(`_ID`) VALUES (1);", _DBConnection.Database)
						);
					}
					#endregion
					foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
					{
						if (dr._CheckState == 0 || dr.ObjectType != 1)
						{
							continue;
						}

						SqlGen_XSD.dbv_tableRow drT = _xsd.dbv_table.FindByTableName(dr.SchemaName, dr.ObjectName);
						SqlGen_XSD.Meta_keyRow drTK = _xsd.Meta_key.FindBySchemaNameTableName(dr.SchemaName, dr.ObjectName);
						SqlGen_XSD.dbv_columnRow[] drCs = drT.GetChildRows("FK_dbv_table_dbv_column") as SqlGen_XSD.dbv_columnRow[];

						#region 数据Key
						/* 
						1.Meta_key已有指定数据Key时，使用此值
						2.否则查找其它表中的存在同名主键列(2列以上)，看作关联型数据
						3.否则将主键作为对象型数据Key，加入到WHERE条件中
						4.否则将自增列作为对象型数据Key，加入到WHERE条件中
						*/
						List<SqlGen_XSD.dbv_columnRow> colKeys = new List<SqlGen_XSD.dbv_columnRow>();
						if (colKeys.Count == 0)
						{
							if (drTK != null)
							{
								string[] aryDataKeys = drTK.PrimaryKeys.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
								for (int i = 0; i < aryDataKeys.Length; i++)
								{
									aryDataKeys[i] = Apq.Data.MySqlClient.Common.ConvertToSqlON(aryDataKeys[i]);
								}
								SqlGen_XSD.dbv_columnRow[] drDataKeys = _xsd.dbv_column.Select(string.Format("SchemaName = {0} AND TableName = {1} AND ColName IN ({2})",
									Apq.Data.MySqlClient.Common.ConvertToSqlON(dr.SchemaName),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(dr.ObjectName),
									string.Join(",", aryDataKeys))) as SqlGen_XSD.dbv_columnRow[];
								colKeys.AddRange(drDataKeys);
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								DataRow[] aryTemp = _xsd.dbv_column.Select(string.Format("TableName <> {0} AND ColName = {1} AND COLUMN_KEY = 'PRI'",
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.TableName),
									Apq.Data.MySqlClient.Common.ConvertToSqlON(drC.ColName)));
								if (aryTemp != null && aryTemp.Length > 0)
								{
									colKeys.Add(drC);
								}
							}
							if (colKeys.Count < 2)
							{
								colKeys.Clear();
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								if ("PRI".Equals(drC.COLUMN_KEY, StringComparison.OrdinalIgnoreCase))
								{
									colKeys.Add(drC);
								}
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								if (drC.is_auto_increment)
								{
									colKeys.Add(drC);
								}
							}
						}
						#endregion
						#region 输出列
						string strCols = string.Empty;
						List<SqlGen_XSD.dbv_columnRow> colInserts = new List<SqlGen_XSD.dbv_columnRow>();
						foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
						{
							if (drC.is_auto_increment && !colKeys.Contains(drC))
							{
								// 跳过无意义的自增列
								continue;
							}
							colInserts.Add(drC);
							strCols += ",`" + drC.ColName + "`";
						}
						#endregion
						#region WHERE语句(替换模式)
						string strWhereTmp = string.Empty;// WHERE 条件

						if (colKeys.Count > 0)
						{
							for (int i = 0; i < colKeys.Count; i++)
							{
								strWhereTmp += string.Format(" AND `{0}`", colKeys[i].ColName) + " = {" + i + "}";
							}
							if (strWhereTmp.Length > 1)
							{
								strWhereTmp = " WHERE" + strWhereTmp.Substring(4);
							}
						}
						else
						{
							string strExMsg = string.Format("无法生成条件的表：{0}，请检查其数据Key设置、关联列名、主键、自增列。", drT.TableName);
							ErrList.AddRow(DateTime.Now, 4, 16, Apq.GlobalObject.UILang["生成表失败"], strExMsg);
							continue;
						}
						#endregion

						if (strCols.Length > 1)
						{
							#region 表说明
							strCols = strCols.Substring(1);
							sb.Append(string.Format(@"

-- 表：`{0}`", drT.TableName));
							#endregion

							long CRow = 0, PageSize = 1000;
							if (tsmiDataDelete.Checked)
							{
								#region 删除原有数据
								while (true)
								{
									#region 从数据库读取一页
									DataSet ds = new DataSet();
									DbDataAdapter dda = dch.CreateAdapter(string.Format(@"SELECT * FROM {0}", drT.TableName));
									if (drTK != null && !string.IsNullOrWhiteSpace(drTK.DataFilter))
									{
										dda.SelectCommand.CommandText += " WHERE " + drTK.DataFilter;
									}
									dda.SelectCommand.CommandText += string.Format(" LIMIT {0},{1};", CRow, PageSize);
									int RowCount = dda.Fill(ds);
									#endregion

									if (RowCount > 0)
									{
										foreach (DataRow drData in ds.Tables[0].Rows)
										{
											#region 删除一行
											List<object> objWhere = new List<object>();
											for (int i = 0; i < colKeys.Count; i++)
											{
												objWhere.Add(Apq.Data.MySqlClient.Common.ConvertToSqlON(drData[colKeys[i].ColName]));
											}
											string strWhere = string.Format(strWhereTmp, objWhere.ToArray());

											sb.Append(string.Format(@"
DELETE FROM `{0}`{1};", drT.TableName, strWhere));
											#endregion
										}
									}
									if (RowCount < PageSize)
									{
										break;
									}
									CRow += RowCount;
								}
								#endregion
							}
							#region 分页查询并输出一个表
							CRow = 0;
							while (true)
							{
								#region 从数据库读取一页
								DataSet ds = new DataSet();
								DbDataAdapter dda = dch.CreateAdapter(string.Format(@"SELECT * FROM {0}", drT.TableName));
								if (drTK != null && !string.IsNullOrWhiteSpace(drTK.DataFilter))
								{
									dda.SelectCommand.CommandText += " WHERE " + drTK.DataFilter;
								}
								dda.SelectCommand.CommandText += string.Format(" LIMIT {0},{1};", CRow, PageSize);
								int RowCount = dda.Fill(ds);
								#endregion

								if (RowCount > 0)
								{
									if (tsmiDataInsert.Checked || tsmiDataDelete.Checked)
									{//批量插入
										sb.Append(string.Format(@"
INSERT INTO `{0}`({1}) VALUES", drT.TableName, strCols));
									}
									foreach (DataRow drData in ds.Tables[0].Rows)
									{
										#region 输出一行
										List<object> objWhere = new List<object>();
										for (int i = 0; i < colKeys.Count; i++)
										{
											objWhere.Add(Apq.Data.MySqlClient.Common.ConvertToSqlON(drData[colKeys[i].ColName]));
										}
										List<string> aryValues = new List<string>();
										for (int i = 0; i < colInserts.Count; i++)
										{
											aryValues.Add(Apq.Data.MySqlClient.Common.ConvertToSqlON(drData[colInserts[i].ColName]));
										}
										string strValues = string.Join(",", aryValues);
										string strWhere = string.Format(strWhereTmp, objWhere.ToArray());

										if (tsmiDataExists.Checked)
										{
											sb.Append(string.Format(@"
INSERT INTO `{0}`({1}) SELECT {2} FROM `_Apq_Ins` WHERE NOT EXISTS(SELECT 1 FROM `{0}`{3});", drT.TableName, strCols, strValues, strWhere));
										}
										if (tsmiDataInsert.Checked || tsmiDataDelete.Checked)
										{
											sb.Append(string.Format(@"
({0}),", strValues));
										}
										#endregion
									}
									if (tsmiDataInsert.Checked || tsmiDataDelete.Checked)
									{//批量插入时将最后一行的,换为;
										sb.Remove(sb.Length - 1, 1);
										sb.Append(";");
									}
								}
								if (RowCount < PageSize)
								{
									break;
								}
								CRow += RowCount;
							}
							#endregion
						}
					}
					#region 文件尾
					if (tsmiDataExists.Checked)
					{
						sb.Append(@"

-- 删除临时表
DROP TABLE IF EXISTS `_Apq_Ins`;");
					}
					sb.Append(@"

COMMIT;
");
					#endregion
					#endregion
				}
				if (tscbSqlProduct.SelectedIndex == 1)
				{
					#region MsSql
					// 为列表中已选中的表生成初始化语句，语句功能：完成将数据库中的数据插入到对应的表中，按主键添加
					sb.Append(string.Format(@"
USE [{0}];

-- 初始数据", _DBConnection.Database)
					);
					foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
					{
						if (dr._CheckState == 0 || dr.ObjectType != 1)
						{
							continue;
						}

						SqlGen_XSD.dbv_tableRow drT = _xsd.dbv_table.FindByTableName(dr.SchemaName, dr.ObjectName);
						SqlGen_XSD.dbv_columnRow[] drCs = drT.GetChildRows("FK_dbv_table_dbv_column") as SqlGen_XSD.dbv_columnRow[];

						#region 计算WHERE语句(替换模式)
						/* 
						1.Meta_key已有指定数据Key时，使用此值
						2.否则查找其它表中的存在同名主键列(2列以上)，看作关联型数据
						3.否则将主键作为对象型数据Key，加入到WHERE条件中
						4.否则将自增列作为对象型数据Key，加入到WHERE条件中
						*/
						List<SqlGen_XSD.dbv_columnRow> colKeys = new List<SqlGen_XSD.dbv_columnRow>();
						if (colKeys.Count == 0)
						{
							SqlGen_XSD.Meta_keyRow drTK = _xsd.Meta_key.FindBySchemaNameTableName(dr.SchemaName, dr.ObjectName);
							if (drTK != null)
							{
								string[] aryDataKeys = drTK.PrimaryKeys.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
								for (int i = 0; i < aryDataKeys.Length; i++)
								{
									aryDataKeys[i] = Apq.Data.SqlClient.Common.ConvertToSqlON(aryDataKeys[i]);
								}
								SqlGen_XSD.dbv_columnRow[] drDataKeys = _xsd.dbv_column.Select(string.Format("SchemaName = {0} AND TableName = {1} AND ColName IN ({2})",
									Apq.Data.SqlClient.Common.ConvertToSqlON(dr.SchemaName),
									Apq.Data.SqlClient.Common.ConvertToSqlON(dr.ObjectName),
									string.Join(",", aryDataKeys))) as SqlGen_XSD.dbv_columnRow[];
								colKeys.AddRange(drDataKeys);
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								DataRow[] aryTemp = _xsd.dbv_column.Select(string.Format("TableName <> {0} AND ColName = {1} AND COLUMN_KEY = 'PRI'",
									Apq.Data.SqlClient.Common.ConvertToSqlON(drC.TableName),
									Apq.Data.SqlClient.Common.ConvertToSqlON(drC.ColName)));
								if (aryTemp != null && aryTemp.Length > 0)
								{
									colKeys.Add(drC);
								}
							}
							if (colKeys.Count < 2)
							{
								colKeys.Clear();
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								if ("PRI".Equals(drC.COLUMN_KEY, StringComparison.OrdinalIgnoreCase))
								{
									colKeys.Add(drC);
								}
							}
						}
						if (colKeys.Count == 0)
						{
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								if (drC.is_auto_increment)
								{
									colKeys.Add(drC);
								}
							}
						}

						string strWhereTmp = string.Empty;// WHERE 条件

						if (colKeys.Count > 0)
						{
							for (int i = 0; i < colKeys.Count; i++)
							{
								strWhereTmp += string.Format(" AND [{0}]", colKeys[i].ColName) + " = {" + i + "}";
							}
							if (strWhereTmp.Length > 1)
							{
								strWhereTmp = " WHERE" + strWhereTmp.Substring(4);
							}
						}
						else
						{
							string strExMsg = string.Format("无法生成条件的表：{0}，请检查其数据Key设置、关联列名、主键、自增列。", drT.TableName);
							ErrList.AddRow(DateTime.Now, 4, 16, Apq.GlobalObject.UILang["生成表失败"], strExMsg);
							continue;
						}
						#endregion

						//将表读到内存，并为每一行生成脚本
						DataSet ds = new DataSet();
						DbDataAdapter dda = dch.CreateAdapter(string.Format(@"SELECT * FROM {0}", drT.TableName));
						dda.Fill(ds);

						if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
						{
							string strCols = string.Empty;
							List<SqlGen_XSD.dbv_columnRow> colInserts = new List<SqlGen_XSD.dbv_columnRow>();
							foreach (SqlGen_XSD.dbv_columnRow drC in drCs)
							{
								if (drC.is_auto_increment && !colKeys.Contains(drC))
								{
									// 跳过无意义的自增列
									continue;
								}
								colInserts.Add(drC);
								strCols += ",[" + drC.ColName + "]";
							}
							if (strCols.Length > 1)
							{
								strCols = strCols.Substring(1);
								sb.Append(string.Format(@"

-- 表：[{0}]", drT.TableName));
							}

							foreach (DataRow drData in ds.Tables[0].Rows)
							{
								List<object> objWhere = new List<object>();
								for (int i = 0; i < colKeys.Count; i++)
								{
									objWhere.Add(Apq.Data.SqlClient.Common.ConvertToSqlON(drData[colKeys[i].ColName]));
								}
								List<string> aryValues = new List<string>();
								for (int i = 0; i < colInserts.Count; i++)
								{
									aryValues.Add(Apq.Data.SqlClient.Common.ConvertToSqlON(drData[colInserts[i].ColName]));
								}
								string strValues = string.Join(",", aryValues);
								string strWhere = string.Format(strWhereTmp, objWhere.ToArray());

								sb.Append(string.Format(@"
IF(NOT EXISTS(SELECT TOP(1) 1 FROM [dbo].[{0}]{3})) INSERT INTO [dbo].[{0}]({1}) VALUES({2})", drT.TableName, strCols, strValues, strWhere));
							}
						}
					}
					sb.Append(@"
");
					#endregion
				}
				File.WriteAllText(sfdMeta.FileName, sb.ToString());
				MessageBox.Show(this, Apq.GlobalObject.UILang["保存成功！"]);

				if (ErrList.ErrXSD.ErrList.Rows.Count > 0)
				{
					ErrList.Show(DockFrame.DockDoc);
				}
			}
		}

		#region 方案
		private void tsbSaveDataCfg_Click(object sender, EventArgs e)
		{
			if (!tscbDataCfg.Items.Contains(tscbDataCfg.Text))
			{
				tscbDataCfg.Items.Add(tscbDataCfg.Text);
			}

			// 将“方案”保存到文件
			SqlGen_XSD xsd = new SqlGen_XSD();
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				if (dr._CheckState == 1)
				{
					xsd.Meta.AddMetaRow(dr._CheckState, dr.ObjectType, dr.SchemaName, dr.ObjectName, string.Empty);
				}
			}
			xsd.Meta_key.Merge(_xsd.Meta_key.Copy());
			xsd.WriteXml(DataCfgFolder + @"\" + tscbDataCfg.Text + ".xml", XmlWriteMode.IgnoreSchema);
			MessageBox.Show(Apq.GlobalObject.UILang["保存成功！"]);
			//tsbSaveDataCfg.Enabled = false;
		}

		private void tscbDataCfg_TextUpdate(object sender, EventArgs e)
		{
			if (!tsbSaveDataCfg.Enabled && !string.IsNullOrWhiteSpace(tscbDataCfg.Text))
			{
				tsbSaveDataCfg.Enabled = true;
			}
			GlobalObject.XmlConfigChain[this.GetType(), "DataCfgName"] = tscbDataCfg.Text;
			GlobalObject.XmlConfigChain.Save();
		}

		private void tscbDataCfg_SelectedIndexChanged(object sender, EventArgs e)
		{
			try
			{
				GlobalObject.XmlConfigChain[this.GetType(), "DataCfgName"] = tscbDataCfg.Text;
				GlobalObject.XmlConfigChain.Save();

				// 读取“方案”文件
				SqlGen_XSD xsd = new SqlGen_XSD();
				xsd.ReadXml(DataCfgFolder + @"\" + tscbDataCfg.Text + ".xml");

				// 清空界面原值
				foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
				{
					dr._CheckState = 0;
				}
				_xsd.Meta_key.Clear();

				// 应用文件
				foreach (SqlGen_XSD.MetaRow drMeta in xsd.Meta.Rows)
				{
					SqlGen_XSD.MetaRow dr = _xsd.Meta.FindByObjectName(drMeta.ObjectType, drMeta.SchemaName, drMeta.ObjectName);
					if (dr != null)
					{
						dr._CheckState = drMeta._CheckState;
					}
				}
				_xsd.Meta_key.Clear();
				_xsd.Meta_key.Merge(xsd.Meta_key.Copy());
				//tsbSaveDataCfg.Enabled = false;
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
		}

		private void btnDataCfgPick_Click(object sender, EventArgs e)
		{
			foreach (DataGridViewRow dgvRow in dataGridView1.SelectedRows)
			{
				DataRowView drv = dgvRow.DataBoundItem as DataRowView;
				if (1.Equals(drv["ObjectType"]))
				{
					SqlGen_XSD.Meta_keyRow drMeta_key = _xsd.Meta_key.FindBySchemaNameTableName(drv["SchemaName"].ToString(), drv["ObjectName"].ToString());
					if (drMeta_key != null)
					{
						drMeta_key.PrimaryKeys = drv["PrimaryKeys"].ToString();
						drMeta_key.DataFilter = drv["DataFilter"].ToString();
					}
					else if (!string.IsNullOrWhiteSpace(drv["PrimaryKeys"].ToString()) || !string.IsNullOrWhiteSpace(drv["DataFilter"].ToString()))
					{
						_xsd.Meta_key.AddMeta_keyRow(
							drv["SchemaName"].ToString(),
							drv["ObjectName"].ToString(),
							drv["PrimaryKeys"].ToString(),
							string.Empty
						);
					}
				}
			}
		}
		#endregion

		#region 选择

		private void tsmiSelectTable_Click(object sender, EventArgs e)
		{
			dataGridView1.EndEdit();
			int _CheckState = Apq.Convert.ChangeType<int>(tsmiSelectTable.Checked);
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				if (dr.ObjectType == 1)
				{
					dr._CheckState = _CheckState;
				}
			}
		}

		private void tsmiSelectProc_Click(object sender, EventArgs e)
		{
			dataGridView1.EndEdit();
			int _CheckState = Apq.Convert.ChangeType<int>(tsmiSelectProc.Checked);
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				if (dr.ObjectType == 2)
				{
					dr._CheckState = _CheckState;
				}
			}
		}

		private void tsmiSelectTrigger_Click(object sender, EventArgs e)
		{
			dataGridView1.EndEdit();
			int _CheckState = Apq.Convert.ChangeType<int>(tsmiSelectTrigger.Checked);
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				if (dr.ObjectType == 3)
				{
					dr._CheckState = _CheckState;
				}
			}
		}

		private void tsmiSelectAll_Click(object sender, EventArgs e)
		{
			dataGridView1.EndEdit();
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				dr._CheckState = 1;
			}
		}

		private void tsmiSelectReverse_Click(object sender, EventArgs e)
		{
			dataGridView1.EndEdit();
			foreach (SqlGen_XSD.MetaRow dr in _xsd.Meta.Rows)
			{
				dr._CheckState = Math.Abs(dr._CheckState - 1);
			}
		}
		#endregion

		#region 数据生成选项
		private void tsmiDataExists_Click(object sender, EventArgs e)
		{
			tssbDataGen.Text = tsmiDataExists.Text;
			if (!tsmiDataExists.Checked)
			{
				tsmiDataExists.Checked = true;

				if (tsmiDataDelete.Checked == tsmiDataExists.Checked)
				{
					tsmiDataDelete.Checked = !tsmiDataExists.Checked;
				}
				if (tsmiDataInsert.Checked == tsmiDataExists.Checked)
				{
					tsmiDataInsert.Checked = !tsmiDataExists.Checked;
				}
			}
		}

		private void tsmiDataDelete_Click(object sender, EventArgs e)
		{
			tssbDataGen.Text = tsmiDataDelete.Text;
			if (!tsmiDataDelete.Checked)
			{
				tsmiDataDelete.Checked = true;

				if (tsmiDataExists.Checked == tsmiDataDelete.Checked)
				{
					tsmiDataExists.Checked = !tsmiDataDelete.Checked;
				}
				if (tsmiDataInsert.Checked == tsmiDataDelete.Checked)
				{
					tsmiDataInsert.Checked = !tsmiDataDelete.Checked;
				}
			}
		}

		private void tsmiDataInsert_Click(object sender, EventArgs e)
		{
			tssbDataGen.Text = tsmiDataInsert.Text;
			if (!tsmiDataInsert.Checked)
			{
				tsmiDataInsert.Checked = true;

				if (tsmiDataExists.Checked == tsmiDataInsert.Checked)
				{
					tsmiDataExists.Checked = !tsmiDataInsert.Checked;
				}
				if (tsmiDataDelete.Checked == tsmiDataInsert.Checked)
				{
					tsmiDataDelete.Checked = !tsmiDataInsert.Checked;
				}
			}
		}
		#endregion

		private void tsbErrList_Click(object sender, EventArgs e)
		{
			if (tsbErrList.Checked)
			{
				ErrList.Show(DockFrame.DockDoc);
			}
			else
			{
				ErrList.Hide();
			}
		}
	}
}